#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

void check_user(std::unordered_map<std::string, struct sockaddr_in>& online_user, const struct sockaddr_in& client, const std::string& clientip, uint16_t clientport)
{
    std::string name = clientip + ":" + std::to_string(clientport);
    if (online_user.find(name) == online_user.end())
    {
        online_user.insert({name, client});
        std::cout << "[" << name << "] add to online user." << std::endl;
        std::cout << "online count: " << online_user.size() << std::endl;
        int count = 1;
        for (const auto& user : online_user)
        {
            std::cout << count++ << "\t";
            std::cout << "ip: " << user.first << " port: " << ntohs(user.second.sin_port) << std::endl;
        }
        std::cout << std::endl;
    }
}
void broad_cast(int sockfd, struct sockaddr_in client, const std::string& info, const std::string clientip, uint16_t clientport)
{
    static std::unordered_map<std::string, struct sockaddr_in> online_user;
    check_user(online_user, client, clientip, clientport);
    for (const auto& user : online_user)
    {
        std::string message = "[";
        message += clientip;
        message += ":";
        message += std::to_string(clientport);
        message += "]# ";
        message += info;
        sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr*)&(user.second), sizeof(user.second));
    }
}

bool SafeCheck(const std::string& cmd)
{
    std::vector<std::string> my_word = { "rm", "mv", "unlink", "cp", \
                                        "sudo", "yum", "install", "kill", "top", "while" };
    for (std::string str : my_word)
    {
        if (cmd.find(str) != std::string::npos)
            return false;
    }
    return true;
}
void ExcuteCommand(int sockfd, struct sockaddr_in client, const std::string& info, const std::string& clientip, uint16_t clientport)
{
    std::string echo;
    do
    {
        if (!SafeCheck(info))
        {
            echo = "Bad man";
            break;
        }
        FILE* fp = popen(info.c_str(), "r");
        if (fp == nullptr)
        {
            echo = "command not found";
            pclose(fp);
            break;
        }
        char buffer[4096];
        while (true)
        {
            char* ret = fgets(buffer, sizeof(buffer), fp);
            if (ret == nullptr)
                break;
            echo += buffer;
        }
        pclose(fp);
    } while (false);
    std::cout << echo << std::endl;
    sendto(sockfd, echo.c_str(), echo.size(), 0, (const struct sockaddr*)&client, sizeof(client));
}


void server_echo(int sockfd, struct sockaddr_in client, const std::string& info, const std::string& clientip, uint16_t clientport)
{
    std::string echo = "[";
    echo += clientip;
    echo += "]@ ";
    echo += info;
    sendto(sockfd, echo.c_str(), echo.size(), 0, (const struct sockaddr*)&client, sizeof(client));
}
